using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using HengTong.Model;
using Microsoft.AspNetCore.Mvc;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Extensions;
using WalkingTec.Mvvm.Mvc;
using HengTong.ViewModel.Daily.SysDailyOvertimeRequestBillVms;
using HengTong.Model.Db.Hr;
using HengTong.Model.Db.Hr.Bill;
using Microsoft.EntityFrameworkCore;
using TiaoTaoHelper.Models;
using TiaoTaoHelper.Wtm.Attributes;
using TiaoTaoHelper.Wtm.Models;


namespace HengTong.Areas.Daily.Controllers
{
    [Area("Daily")]
    [AuthorizeJwtWithCookie]
    [ActionDescription("加班申请")]
    [ApiController]
    [Route("api/SysDailyOvertimeRequestBill")]
    public partial class SysDailyOvertimeRequestBillController : BaseApiController
    {
        [ActionDescription("Sys.Search")]
        [HttpPost("Search")]
        public IActionResult Search(SysDailyOvertimeRequestBillSearcher searcher)
        {
            if (ModelState.IsValid)
            {
                var vm = Wtm.CreateVM<SysDailyOvertimeRequestBillListVm>(passInit: true);
                vm.Searcher = searcher;
                return Ok(vm.GetJsonForApi());
            }
            else
            {
                return BadRequest(ModelState.GetErrorJson());
            }
        }

        [ActionDescription("Sys.Get")]
        [HttpGet("{id}")]
        public SysDailyOvertimeRequestBillVm Get(string id)
        {
            var vm = Wtm.CreateVM<SysDailyOvertimeRequestBillVm>(id);
            return vm;
        }

        [ActionDescription("Sys.Create")]
        [HttpPost("Add")]
        [PreventDuplicateSubmit]
        public async Task<IActionResult> Add(SysDailyOvertimeRequestBillVm vm)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                await vm.DoAddAsync();
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState.GetErrorJson());
                }
                else
                {
                    return Ok(vm.Entity);
                }
            }
        }

        [ActionDescription("Sys.Edit")]
        [PreventDuplicateSubmit]
        [HttpPut("Edit")]
        public async Task<IActionResult> Edit(SysDailyOvertimeRequestBillVm vm)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                await vm.DoEditAsync(false);
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState.GetErrorJson());
                }
                else
                {
                    return Ok(vm.Entity);
                }
            }
        }

        [HttpPost("BatchDelete")]
        [ActionDescription("Sys.Delete")]
        [PreventDuplicateSubmit]
        public IActionResult BatchDelete(string[] ids)
        {
            var vm = Wtm.CreateVM<SysDailyOvertimeRequestBillBatchVm>();
            if (ids != null && ids.Any())
            {
                vm.Ids = ids;
            }
            else
            {
                return Ok();
            }

            if (!ModelState.IsValid || !vm.DoBatchDelete())
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                return Ok(ids.Count());
            }
        }


        [ActionDescription("Sys.Export")]
        [HttpPost("ExportExcel")]
        public IActionResult ExportExcel(SysDailyOvertimeRequestBillSearcher searcher)
        {
            var vm = Wtm.CreateVM<SysDailyOvertimeRequestBillListVm>();
            vm.Searcher = searcher;
            vm.SearcherMode = ListVMSearchModeEnum.Export;
            return vm.GetExportData();
        }

        [ActionDescription("Sys.CheckExport")]
        [HttpPost("ExportExcelByIds")]
        public IActionResult ExportExcelByIds(string[] ids)
        {
            var vm = Wtm.CreateVM<SysDailyOvertimeRequestBillListVm>();
            if (ids != null && ids.Any())
            {
                vm.Ids = new List<string>(ids);
                vm.SearcherMode = ListVMSearchModeEnum.CheckExport;
            }

            return vm.GetExportData();
        }

        [ActionDescription("Sys.DownloadTemplate")]
        [HttpGet("GetExcelTemplate")]
        public IActionResult GetExcelTemplate()
        {
            var vm = Wtm.CreateVM<SysDailyOvertimeRequestBillImportVm>();
            var qs = new Dictionary<string, string>();
            foreach (var item in Request.Query.Keys)
            {
                qs.Add(item, Request.Query[item]);
            }

            vm.SetParms(qs);
            var data = vm.GenerateTemplate(out string fileName);
            return File(data, "application/vnd.ms-excel", fileName);
        }

        [ActionDescription("Sys.Import")]
        [HttpPost("Import")]
        public ActionResult Import(SysDailyOvertimeRequestBillImportVm vm)
        {
            if (vm != null && (vm.ErrorListVM.EntityList.Count > 0 || !vm.BatchSaveData()))
            {
                return BadRequest(vm.GetErrorJson());
            }
            else
            {
                return Ok(vm?.EntityList?.Count ?? 0);
            }
        }


        [HttpGet("GetSysPersons")]
        public ActionResult GetSysPersons()
        {
            return Ok(DC.Set<SysPerson>().Where(x => x.GetType() == typeof(SysPerson))
                .GetSelectListItems(Wtm, x => x.Name));
        }

        [HttpGet("GetSysGroups")]
        public ActionResult GetSysGroups()
        {
            return Ok(DC.Set<SysGroup>().Where(x => !x.IsDisabled).OrderBy(x => x.Order ?? 99.99m)
                .Select(x => new { Value = x.ID, Text = x.GroupName }).ToList());
        }

        [HttpGet("GetSysOrgs")]
        public ActionResult GetSysOrgs()
        {
            return Ok(DC.Set<SysOrg>().GetSelectListItems(Wtm, x => x.Name));
        }


        [ActionDescription("预测编码")]
        [HttpGet("PredictCode")]
        public async Task<Result<string>> PredictCode()
        {
            var vm = Wtm.CreateVM<SysDailyOvertimeRequestBillVm>();
            return await vm.PredictCodeAsync();
        }


        [HttpPost("[action]")]
        [ActionDescription("流程审批")]
        public async Task<ActionResult> Approve(SysDailyOvertimeRequestBillVm vm)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState.GetErrorJson());
            }
            else
            {
                await vm.ApproveAsync(false);
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState.GetErrorJson());
                }
                else
                {
                    return Ok(vm.Entity);
                }
            }
        }

        [ActionDescription("获取可用于调休的加班记录")]
        [HttpGet("[action]")]
        public async Task<Result<List<OvertimeForCompOffView>>> GetAvailableOvertimeForCompOff(
            [FromQuery] string personIdOrStaffNo,
            [FromQuery] Guid? compOffRequestBillId = null)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(personIdOrStaffNo))
                {
                    return new Result<List<OvertimeForCompOffView>>("员工ID或工号不能为空");
                }

                bool isGuid = Guid.TryParse(personIdOrStaffNo, out var personId);

                // 修改场景:获取该调休申请已关联的加班记录
                if (compOffRequestBillId.HasValue)
                {
                    var linkedOvertimeIds = await DC.Set<SysCompOffOvertimeLink>()
                        .Where(x => x.CompOffRequestBillId == compOffRequestBillId.Value)
                        .Select(x => x.OvertimeRequestBillId)
                        .ToListAsync();

                    var data = await DC.Set<SysDailyOvertimeRequestBill>()
                        .Where(x => linkedOvertimeIds.Contains(x.ID))
                        .OrderByDescending(x => x.StartTime)
                        .Select(x => new OvertimeForCompOffView
                        {
                            ID = x.ID,
                            BillCode = x.BillCode,
                            PersonId = x.PersonId,
                            StaffNo = x.StaffNo,
                            Name = x.Name,
                            StartTime = x.StartTime,
                            EndTime = x.EndTime,
                            OvertimeHours = x.OvertimeHours,
                            RemainingCompOffHours = x.RemainingCompOffHours,
                            CompensationType = x.CompensationType,
                            Reason = x.Reason
                        })
                        .ToListAsync();

                    return new Result<List<OvertimeForCompOffView>>(data);
                }

                // 新增场景:获取可用于调休的加班记录 (近两个月内，已完成且等时调休，剩余调休小时数大于0，且未被其他调休申请关联)
                var threeMonthsAgo = DateTime.Now.AddMonths(-3);
                var twoMonthsAgo = DateTime.Now.AddMonths(-2);
                

                // 获取该员工正在执行中的调休申请关联的加班ID
                var inProgressOvertimeIds = await DC.Set<SysCompOffOvertimeLink>()
                    .Where(x => x.CompOffRequestBill.WorkflowStatus != WorkflowStatus.已完成
                                && x.CompOffRequestBill.WorkflowStatus != WorkflowStatus.已取消)
                    .Where(x => isGuid
                        ? x.CompOffRequestBill.PersonId == personId
                        : x.CompOffRequestBill.StaffNo == personIdOrStaffNo)
                    .Select(x => x.OvertimeRequestBillId)
                    .Distinct()
                    .ToListAsync();

                var query = DC.Set<SysDailyOvertimeRequestBill>()
                    .Where(x => x.WorkflowStatus == WorkflowStatus.已完成)
                    .Where(x => x.CompensationType == OvertimeCompensationType.等时调休)
                    .Where(x => x.RemainingCompOffHours > 0 && x.StartTime >= twoMonthsAgo)
                    .Where(x => !inProgressOvertimeIds.Contains(x.ID));

                if (isGuid)
                {
                    query = query.Where(x => x.PersonId == personId);
                }
                else
                {
                    query = query.Where(x => x.StaffNo == personIdOrStaffNo);
                }

                var availableData = await query
                    .OrderByDescending(x => x.StartTime)
                    .Select(x => new OvertimeForCompOffView
                    {
                        ID = x.ID,
                        BillCode = x.BillCode,
                        PersonId = x.PersonId,
                        StaffNo = x.StaffNo,
                        Name = x.Name,
                        StartTime = x.StartTime,
                        EndTime = x.EndTime,
                        OvertimeHours = x.OvertimeHours,
                        RemainingCompOffHours = x.RemainingCompOffHours,
                        CompensationType = x.CompensationType,
                        Reason = x.Reason
                    })
                    .ToListAsync();

                return new Result<List<OvertimeForCompOffView>>(availableData);
            }
            catch (Exception ex)
            {
                return new Result<List<OvertimeForCompOffView>>($"获取加班记录失败:{ex.Message}");
            }
        }


        public class OvertimeForCompOffView
        {
            public Guid ID { get; set; }
            public string BillCode { get; set; }
            public Guid? PersonId { get; set; }
            public string StaffNo { get; set; }
            public string Name { get; set; }
            public DateTime? StartTime { get; set; }
            public DateTime? EndTime { get; set; }
            public decimal? OvertimeHours { get; set; }
            public decimal? RemainingCompOffHours { get; set; }
            public OvertimeCompensationType? CompensationType { get; set; }
            public string Reason { get; set; }
        }
    }
}